﻿using System;
using Framework.Core.Cache;
using Xunit;

namespace Framework.Tests.Core.Cache
{
    public class DictionnaryStorageTest
    {
        private static IStorage GetStorage()
        {
            return new DictionaryStorage(4, new TimeSpan(1, 0, 0, 0));
        }

        [Fact]
        public void Should_return_null()
        {
            var target = GetStorage();
            object actual;
            Assert.False(target.TryGet("pouet", out actual));
            Assert.Null(actual);
        }

        [Fact]
        public void Should_Invalid_cache()
        {
            const string key = "pouet";
            object actual;
            object value = 1;
            var cache = new DictionaryStorage(3, new TimeSpan(0, 1, 0, 0).Negate());

            Assert.False(cache.TryGet(key, out actual));
            cache.Update(key, new TimeSpan(1, 0, 0, 0), value);
            cache.Update("2", new TimeSpan(1, 0, 0, 0), value);
            cache.Update("3", new TimeSpan(1, 0, 0, 0), value);
            cache.Update("4", new TimeSpan(1, 0, 0, 0), value);
            cache.Update("5", new TimeSpan(1, 0, 0, 0), value);
            Assert.False(cache.TryGet(key, out actual));
        }

        [Fact]
        public void Should_return_cache_and_flush()
        {
            var target = GetStorage();
            const string key = "toto";
            const int i = 1;
            object actual;

            target.Update(key, new TimeSpan(1, 0, 0, 0), i);

            Assert.True(target.TryGet(key, out actual));
            Assert.NotNull(actual);

            target.Flush();
            Assert.False(target.TryGet(key, out actual));
        }

        [Fact]
        public void Should_Collect_if_is_out_of_size()
        {
            var targetWithLimitSize = new DictionaryStorage(2, new TimeSpan(1, 0, 0, 0));

            object cache;
            targetWithLimitSize.Update("1", new TimeSpan(1, 0, 0, 0), 1);
            Assert.True(targetWithLimitSize.TryGet("1", out cache));
            targetWithLimitSize.Update("2", new TimeSpan(0, 1, 0, 0), 1);
            Assert.True(targetWithLimitSize.TryGet("2", out cache));
            Assert.True(targetWithLimitSize.TryGet("1", out cache));
            targetWithLimitSize.Update("3", new TimeSpan(0, 1, 0, 0), 1);

            Assert.True(targetWithLimitSize.TryGet("3", out cache));
        }
    }
}